
#include "pika_hal_deque.h"


pika_hal_deque_t* pika_hal_deque_create(int maxlen) {
    pika_hal_deque_t* deque = (pika_hal_deque_t*)pikaMalloc(sizeof(pika_hal_deque_t));
    if (NULL == deque) {
        return PIKA_RES_ERR_MEMORY_ERROR;
    }
    return pika_hal_deque_init(deque, maxlen);
}

int pika_hal_deque_init(pika_hal_deque_t* deque, int maxlen) {
    
    if (NULL == deque) {
        return PIKA_RES_ERR_ASSERT;
    }
    deque->head = NULL;
    deque->tail = NULL;
    deque->count = 0;
    deque->maxlen = maxlen;
#if PIKA_HAL_DQUEUE_MUTEX_ENABLE
    int err = pika_platform_thread_lock_init(&deque->lock);
    if (err < 0){
        return PIKA_RES_ERR_RUNTIME_ERROR;
    }
    return PIKA_RES_OK;
#endif
}

int pika_hal_deque_appendTail(pika_hal_deque_t* deque, void* value) {
    int ret = PIKA_RES_OK;
#if PIKA_HAL_DQUEUE_MUTEX_ENABLE
    pika_platform_thread_lock_acquire(&deque->lock, pika_true, -1);
#endif
    if (deque->maxlen > 0 && deque->count >= deque->maxlen) {
        ret = PIKA_RES_ERR_FULL;  // 队列已满
        goto __exit;
    }

    Node* node = (Node*)pikaMalloc(sizeof(Node));
    if (node == NULL) {
        ret = PIKA_RES_ERR_MEMORY_ERROR;  // 内存分配失败
        goto __exit;
    }
    node->data = value;
    node->prev = deque->tail;
    node->next = NULL;

    if (deque->tail) {
        deque->tail->next = node;
    } else {
        deque->head = node;
    }
    deque->tail = node;
    deque->count++;

__exit:
#if PIKA_HAL_DQUEUE_MUTEX_ENABLE
    pika_platform_thread_lock_release(&deque->lock);
#endif
    return ret;
}

int pika_hal_deque_appendHead(pika_hal_deque_t* deque, void* value) {
    int ret = PIKA_RES_OK;
#if PIKA_HAL_DQUEUE_MUTEX_ENABLE
    pika_platform_thread_lock_acquire(&deque->lock, pika_true, -1);
#endif
    if (deque->maxlen > 0 && deque->count >= deque->maxlen) {
        ret = PIKA_RES_ERR_FULL;  // 队列已满
        goto __exit;
    }

    Node* node = (Node*)pikaMalloc(sizeof(Node));
    if (node == NULL) {
        ret = PIKA_RES_ERR_MEMORY_ERROR;  // 内存分配失败
        goto __exit;
    }
    node->data = value;
    node->prev = NULL;
    node->next = deque->head;

    if (deque->head) {
        deque->head->prev = node;
    } else {
        deque->tail = node;
    }
    deque->head = node;
    deque->count++;

__exit:
#if PIKA_HAL_DQUEUE_MUTEX_ENABLE
    pika_platform_thread_lock_release(&deque->lock);
#endif
    return ret;
}

int pika_hal_deque_popHead(pika_hal_deque_t* deque, void** value) {
    int ret = PIKA_RES_OK;
#if PIKA_HAL_DQUEUE_MUTEX_ENABLE
    pika_platform_thread_lock_acquire(&deque->lock, pika_true, -1);
#endif
    if (deque->count == 0) {
        ret = PIKA_RES_ERR_EMPTY;  // 队列为空
        goto __exit;
    }

    *value = deque->head->data;
    Node* temp = deque->head;
    deque->head = deque->head->next;
    if (deque->head) {
        deque->head->prev = NULL;
    } else {
        deque->tail = NULL;
    }
    deque->count--;
    pikaFree(temp, sizeof(Node));

__exit:
#if PIKA_HAL_DQUEUE_MUTEX_ENABLE
    pika_platform_thread_lock_release(&deque->lock);
#endif
    return ret;
}

int pika_hal_deque_popTail(pika_hal_deque_t* deque, void** value) {
    int ret = PIKA_RES_OK;
#if PIKA_HAL_DQUEUE_MUTEX_ENABLE
    pika_platform_thread_lock_acquire(&deque->lock, pika_true, -1);
#endif
    if (deque->count == 0) {
        ret = PIKA_RES_ERR_EMPTY;  // 队列为空
        goto __exit;
    }

    *value = deque->tail->data;
    Node* temp = deque->tail;
    deque->tail = deque->tail->prev;
    if (deque->tail) {
        deque->tail->next = NULL;
    } else {
        deque->head = NULL;
    }
    deque->count--;
    pikaFree(temp, sizeof(Node));

__exit:
#if PIKA_HAL_DQUEUE_MUTEX_ENABLE
    pika_platform_thread_lock_release(&deque->lock);
#endif
    return ret;
}

int pika_hal_deque_peekHead(pika_hal_deque_t* deque, void** value) {
    if (deque->count == 0) {
        return PIKA_RES_ERR_RUNTIME_ERROR;  // 队列为空
    }

#if PIKA_HAL_DQUEUE_MUTEX_ENABLE
    pika_platform_thread_lock_acquire(&deque->lock, pika_true, -1);
#endif
    *value = deque->head->data;
#if PIKA_HAL_DQUEUE_MUTEX_ENABLE
    pika_platform_thread_lock_release(&deque->lock);
#endif

    return PIKA_RES_OK;
}

int pika_hal_deque_peekTail(pika_hal_deque_t* deque, void** value) {
    if (deque->count == 0) {
        return PIKA_RES_ERR_RUNTIME_ERROR;  // 队列为空
    }

#if PIKA_HAL_DQUEUE_MUTEX_ENABLE
    pika_platform_thread_lock_acquire(&deque->lock, pika_true, -1);
#endif
    *value = deque->tail->data;
#if PIKA_HAL_DQUEUE_MUTEX_ENABLE
    pika_platform_thread_lock_release(&deque->lock);
#endif

    return PIKA_RES_OK;
}

size_t pika_hal_deque_getCount(pika_hal_deque_t* deque) {
#if PIKA_HAL_DQUEUE_MUTEX_ENABLE
    pika_platform_thread_lock_acquire(&deque->lock, pika_true, -1);
#endif
    size_t count = deque->count;
#if PIKA_HAL_DQUEUE_MUTEX_ENABLE
    pika_platform_thread_lock_release(&deque->lock);
#endif
    return count;
}

pika_bool pika_hal_deque_isEmpty(pika_hal_deque_t* deque) {
    return deque->count == 0;
}

pika_bool pika_hal_deque_isFull(pika_hal_deque_t* deque) {
    return deque->count == deque->maxlen;
}


void pika_hal_deque_deinit(pika_hal_deque_t* deque) {
#if PIKA_HAL_DQUEUE_MUTEX_ENABLE
    pika_platform_thread_lock_acquire(&deque->lock, pika_true, -1);
#endif
    while (deque->head != NULL) {
        Node* temp = deque->head;
        deque->head = deque->head->next;
        pikaFree(temp, sizeof(Node));
    }
    deque->head = NULL;
    deque->tail = NULL;
    deque->count = 0;
    deque->maxlen = 0;
#if PIKA_HAL_DQUEUE_MUTEX_ENABLE
    pika_platform_thread_lock_release(&deque->lock);
    pika_platform_thread_lock_destroy(&deque->lock);
#endif
}

void pika_hal_deque_delete(pika_hal_deque_t* deque){
    pika_hal_deque_deinit(deque);
    pikaFree(deque, sizeof(pika_hal_deque_t));
}

